home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / encorsrc.lha / encore_sources / sys / arith.t < prev    next >
Text File  |  1988-05-02  |  12KB  |  358 lines

  1. (herald arith (env tsys))
  2.  
  3. ;;; Copyright (c) 1985 Yale University
  4. ;;;     Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
  5. ;;; This material was developed by the T Project at the Yale University Computer 
  6. ;;; Science Department.  Permission to copy this software, to redistribute it, 
  7. ;;; and to use it for any purpose is granted, subject to the following restric-
  8. ;;; tions and understandings.
  9. ;;; 1. Any copy made of this software must include this copyright notice in full.
  10. ;;; 2. Users of this software agree to make their best efforts (a) to return
  11. ;;;    to the T Project at Yale any improvements or extensions that they make,
  12. ;;;    so that these may be included in future releases; and (b) to inform
  13. ;;;    the T Project of noteworthy uses of this software.
  14. ;;; 3. All materials developed as a consequence of the use of this software
  15. ;;;    shall duly acknowledge such use, in accordance with the usual standards
  16. ;;;    of acknowledging credit in academic research.
  17. ;;; 4. Yale has made no warrantee or representation that the operation of
  18. ;;;    this software will be error-free, and Yale is under no obligation to
  19. ;;;    provide any services, by way of maintenance, update, or otherwise.
  20. ;;; 5. In conjunction with products arising from the use of this material,
  21. ;;;    there shall be no use of the name of the Yale University nor of any
  22. ;;;    adaptation thereof in any advertising, promotional, or sales literature
  23. ;;;    without prior written consent from Yale in each case.
  24. ;;;
  25.  
  26. ;;; Copyright (c) 1983, 1984 Yale University
  27.  
  28. ;;;; Arithmetical and mathematical and generical
  29.  
  30. ;;; Basic predicates
  31.  
  32. (define (integer? x)
  33.   (or (fixnum? x) (bignum? x)))
  34.  
  35. (define-constant (number? x)
  36.   (or (fixnum? x)
  37.       (true? (extended-number-type x))))
  38.  
  39. (define float? double-float?)
  40.  
  41. (define real? number?)
  42.  
  43. (define short-float? false)    ;Fix later for T3
  44.  
  45. ;;; (define complex? number?)
  46.  
  47. (define-constant %%fixnum-number-type 0)
  48. (define-constant %%flonum-number-type 1)
  49. (define-constant %%bignum-number-type 2)
  50. (define-constant %%ratio-number-type  3)
  51.  
  52. (define-constant %%number-of-number-types 4)
  53.  
  54. (define-operation (extended-number-type obj) nil)
  55.  
  56. (define-operation (unguarded-version proc) proc)
  57.  
  58. (define-integrable (number-type obj op)
  59.   (cond ((fixnum? obj) %%fixnum-number-type)
  60.         ((and (extend? obj)
  61.               (extended-number-type obj))
  62.          => identity)
  63.         (else (losing-number-type obj op))))
  64.  
  65. (define (losing-number-type obj op)
  66.   (number-type (error "non-numeric argument~%  (~S ... ~S ...)" op obj)
  67.                 op))
  68.  
  69. (define-operation (set-dispatch generic-op-frob type1 type2 procedure))
  70.  
  71.  
  72.  
  73. (define (make-two-arg-number-routine identifier)
  74.   (let ((table (make-vector %%number-of-number-types)))
  75.     (let ((lose
  76.            (lambda (n1 n2)
  77.              (error "generic number routine not defined for this ~
  78.                      combination of types~%  (~S~_~S~_~S)"
  79.                     identifier n1 n2))))
  80.       (do ((i 0 (fx+ i 1)))
  81.           ((fx>= i %%number-of-number-types)
  82.            (object (lambda (n1 n2)
  83.                      ((vref (vref table (number-type n1 identifier))
  84.                             (number-type n2 identifier))
  85.                       n1 n2))
  86.                    ((set-dispatch self type1 type2 proc)
  87.                     (vset (vref table type1) type2 (unguarded-version proc)))
  88.                    ((identification self) identifier)))
  89.         (let ((v (make-vector %%number-of-number-types)))
  90.           (vset table i v)
  91.           (vector-fill v lose))))))
  92.  
  93. ;;; The dispatch tables
  94.  
  95. (define %%add      (make-two-arg-number-routine 'add))
  96. (define %%subtract (make-two-arg-number-routine 'subtract))
  97. (define %%multiply (make-two-arg-number-routine 'multiply))
  98. (define %%divide   (make-two-arg-number-routine 'divide))
  99. (define %%quotient (make-two-arg-number-routine 'quotient))
  100. (define %%less?    (make-two-arg-number-routine 'less?))
  101. (define %%equal?   (make-two-arg-number-routine 'number-equal?))
  102.  
  103. (define (set-dispatches type1 type2 + - * / quotient < =)
  104.   (set-dispatch %%add       type1 type2 +)
  105.   (set-dispatch %%subtract  type1 type2 -)
  106.   (set-dispatch %%multiply  type1 type2 *)
  107.   (set-dispatch %%divide    type1 type2 /)
  108.   (set-dispatch %%quotient  type1 type2 quotient)
  109.   (set-dispatch %%less?     type1 type2 <)
  110.   (set-dispatch %%equal?    type1 type2 =))
  111.  
  112. ;;; QUOTIENT
  113. (define-constant divide %%divide)
  114. (define-constant / divide) 
  115. (define-constant div2 quotient&remainder)
  116. (define-constant quotient %%quotient)
  117.  
  118. (define (quotient&remainder x y)
  119.   (let ((div2-kludgily (lambda (x y)
  120.                          (let ((q (quotient x y)))
  121.                            (return q (subtract x (%multiply q y)))))))
  122.     (cond ((fixnum? y)
  123.            (cond ((fixnum? x)
  124.                   (return (fx/ x y) (fixnum-remainder x y)))
  125.                  ((bignum? x) (b-f-div2 x y))
  126.                  (else
  127.                   (div2-kludgily x y))))
  128.           ((bignum? y)
  129.            (cond ((fixnum? x) (return 0 x))
  130.                  ((bignum? x) (bignum-div2 x y))
  131.                  (else        (div2-kludgily x y))))
  132.           (else (div2-kludgily x y)))))
  133.  
  134. ;++ Kludge - add to dispatch table later.
  135.  
  136. (define (%%remainder x y)
  137.   (let ((remainder-kludgily  (lambda (x y)
  138.                                (subtract x (%multiply (quotient x y) y)))))
  139.     (cond ((fixnum? y)
  140.            (cond ((fixnum? x) (fixnum-remainder x y))
  141.                  ((bignum? x) (b-f-remainder x y))
  142.                  (else        (remainder-kludgily x y))))
  143.           ((bignum? y)
  144.            (cond ((fixnum? x)
  145.                   (if (and (fx= x most-negative-fixnum)       ;Thanks to Joe Stoy!
  146.                            (= y (negate most-negative-fixnum)))
  147.                       0
  148.                       x))
  149.                  ((bignum? x) (bignum-remainder x y))
  150.                  (else        (remainder-kludgily x y))))
  151.           (else (remainder-kludgily x y)))))
  152.  
  153. (define-constant (odd? x) 
  154.   (odd?-aux x odd?))
  155.  
  156. (define-constant (even? x) 
  157.   (not (odd?-aux x even?)))
  158.  
  159. (define (odd?-aux x who)
  160.   (let ((x (check-arg integer? x who)))
  161.     (cond ((fixnum? x) (fixnum-odd? x))
  162.           (else        (bignum-odd? x)))))
  163.  
  164. (define-integrable (nonnegative-integer? n)
  165.   (and (integer? n) (not-negative? n)))
  166.  
  167. (define-integrable (fixnum-length x)
  168.   (if (fx>= x 0)
  169.       (fixnum-howlong x)
  170.       (fixnum-howlong (fx- -1 x))))
  171.  
  172. (define (integer-length x) 
  173.   (let ((x (enforce integer? x)))
  174.     (cond ((fixnum? x)
  175.        (fixnum-length x))
  176.           (else
  177.        (if (>= x 0)
  178.            (bignum-howlong x)
  179.            (bignum-howlong (subtract -1 x)))))))
  180.  
  181. (define (ash num amount)
  182.   (let ((num    (enforce nonnegative-integer? num))
  183.         (amount (enforce fixnum? amount)))
  184.     (%ash num amount)))
  185.  
  186. (define (%ash num amount)           ; See PRINT-FLONUM
  187.   (cond ((fixnum? num)
  188.          (cond ((fx> amount 0)
  189.                 (let ((num-length (integer-length num)))
  190.                   (let ((result-length (fx+ num-length amount)))
  191.                     (cond ((fx> result-length *u-bits-per-fixnum*)
  192.                            (fixnum-ashl-bignum num amount))
  193.                           (else
  194.                            (fixnum-ashl num amount))))))
  195.                (else
  196.                 (fixnum-ashr num (fx- 0 amount)))))
  197.         (else
  198.          (cond ((fx> amount 0)
  199.                 (bignum-ashl num amount))
  200.                ((fx= amount 0)
  201.                 num)
  202.                (else
  203.                 (let ((amount (fx- 0 amount))
  204.                       (num-length (integer-length num)))
  205.                   (let ((result-length (fx- num-length amount)))
  206.                     (cond ((fx> result-length *u-bits-per-fixnum*)
  207.                            (bignum-ashr num amount))
  208.                           ((fx<= result-length 0) 0)
  209.                           (else
  210.                            (bignum-ashr-fixnum num amount))))))))))
  211.  
  212. (define (bignum-lossage op)
  213.   (lambda (x y)
  214.     (error "~S not yet implemented for bignums"
  215.        (list op x y))))
  216.  
  217. (define %%logand  (bignum-lossage 'logand))
  218. (define %%logior  (bignum-lossage 'logior))
  219. (define %%logxor  (bignum-lossage 'logxor))
  220.  
  221. (define bit-field fixnum-bit-field)
  222. (define set-bit-field set-fixnum-bit-field)
  223.  
  224. (define (max2 n1 n2)
  225.   (if (greater? n1 n2) n1 n2))
  226.  
  227. (define (max number . numbers)
  228.   (do ((n numbers (cdr n))
  229.        (result number (max2 result (car n))))
  230.       ((null? n) result)))
  231.  
  232. (define (min2 n1 n2)
  233.   (if (less? n1 n2) n1 n2))
  234.  
  235. (define (min number . numbers)
  236.   (do ((n numbers (cdr n))
  237.        (result number (min2 result (car n))))
  238.       ((null? n) result)))
  239.  
  240. (define (abs n) (if (less? n 0) (negate n) n))
  241.  
  242. ;;; Raise any number to a fixnum power > 1.
  243.  
  244. (define (raise-to-fixnum-power base power)
  245.   (do ((bit (fixnum-ashl 1 (fx- (fixnum-howlong power) 2))
  246.             (fixnum-ashr bit 1))
  247.        (result base (let ((result^2 (%multiply result result)))
  248.                       (if (fx= (fixnum-logand power bit) 0)
  249.                           result^2
  250.                         (%multiply result^2 base)))))
  251.       ((fx= bit 0) result)))
  252.  
  253. ;;; (define (foo base power)
  254. ;;;   (do ((p power (fixnum-ashr p 1))
  255. ;;;        (temp base (* temp temp))
  256. ;;;        (result 1 (if (fixnum-odd? p) (* temp result) result)))
  257. ;;;       ((fx= p 0) result)))
  258.  
  259. ;;; Has to deal with flonums
  260.  
  261. (define (expt x y)
  262.   (let ((x (enforce number? x))
  263.         (y (enforce fixnum? y)))
  264.     (cond ((fx= y 1) x)
  265.           ((fx< y 0) (/ 1 (expt x (fx- 0 y))))
  266.           ((fx= y 0) 1)                 ; ??? if x is float, should return 1.0?
  267.           ((not (fixnum? x)) (raise-to-fixnum-power x y))
  268.           ((fx= x 0) 0)
  269.           ((fx= x 1) 1)
  270.           ((fx= x -1) (if (fixnum-odd? y) -1 1))
  271.           (else (raise-to-fixnum-power x y)))))
  272.  
  273. ;;; Euclid's algorithm.  Binary GCD would probably be better, esp. on machines
  274. ;;; like the 68000 that lack divide instructions.
  275.  
  276. (define (gcd p q)
  277.   (do ((p (abs p) q)
  278.        (q (abs q) (remainder p q)))
  279.     ((number-equal? q 0) p)))
  280.  
  281. (define-integrable (signum x)
  282.   (let ((x (enforce number? x)))
  283.     (if (zero? x) x (/ x (abs x)))))
  284.  
  285. (define (modulo x y)
  286.   (let ((x (enforce integer? x))
  287.         (y (enforce integer? y)))
  288.     (cond ((= (signum x) (signum y))
  289.            (remainder x y))
  290.           (else
  291.            (let ((r (remainder x y)))
  292.              (cond ((= r 0) 0)
  293.                    (else
  294.                     (+ y r))))))))
  295.  
  296. (define-constant mod modulo)
  297.  
  298. ;;; Return largest multiple N of Y such that N <= X
  299. ;;; Awful, awful kludgey definition.
  300.  
  301. (define (floor x y)
  302.   (subtract x (mod x y)))
  303.  
  304. ;;; Return smallest multiple N of Y such that N >= X
  305. ;;; Awful, awful kludgey definition.
  306.  
  307. (define (ceiling x y)
  308.   (floor (%add x (subtract y 1)) y))
  309.  
  310. ;;; Coerce to integer.
  311. ;;; Awful, awful kludgey definition.
  312.  
  313. (define truncate ->integer)
  314.  
  315. (define (->integer x)
  316.   (cond ((integer? x) x)
  317.         ((float? x) (flonum->integer x))
  318.         ((ratio? x) (quotient (numerator x) (denominator x)))
  319.         (else (->integer (error "can't coerce to integer~%  (~S ~S)"
  320.                                 '->integer x)))))
  321.  
  322. ;;; Coerce to floating point number.
  323. ;;; Awful, awful kludgey definition.
  324.  
  325. (define (->float x)
  326.   (cond ((float? x) x)
  327.         ((fixnum? x) (fixnum->flonum x))
  328.         ((bignum? x) (bignum->flonum x))
  329.         ((ratio? x) (flonum-divide (->float (numerator x))
  330.                                    (->float (denominator x))))
  331.         (else
  332.          (->float (error "can't coerce to floating point number~%  (~S ~S)"
  333.                          '->float x)))))
  334. (define-constant most-positive-fixnum-as-flonum 
  335.   (fixnum->flonum most-positive-fixnum))
  336.  
  337. (define-constant most-negative-fixnum-as-flonum 
  338.   (fixnum->flonum most-negative-fixnum))
  339.  
  340. (define (flonum->integer x)
  341.   (cond ((fl> x most-positive-fixnum-as-flonum)
  342.          (receive (sig mag exp) (integer-decode-float x)
  343.            (ash mag exp)))
  344.         ((fl< x most-negative-fixnum-as-flonum)
  345.          (receive (sig mag exp) (integer-decode-float x)
  346.            (let ((n (ash mag exp)))
  347.              (cond ((bignum? n) 
  348.                     (bignum-negate! n) 
  349.                     n)
  350.                    (else
  351.                     (fx-negate n))))))
  352.         (else (flonum->fixnum x))))
  353.  
  354. (define (flonum-quotient x y)
  355.   (flonum->integer (flonum-divide x y)))
  356.  
  357. (define integer->flonum fixnum->flonum)
  358.